package com.zf.captcha.hutool;

import cn.hutool.captcha.*;
import cn.hutool.captcha.generator.MathGenerator;
import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.math.Calculator;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * hutool-captcha 生成图形验证码
 * 使用 AbstractCaptcha 的子类对象创建验证码，有四个子类：
 * - LineCaptcha：线条干扰
 * - CircleCaptcha：圆圈干扰
 * - ShearCaptcha：形变的字符
 * - GifCaptcha：gif格式，动态图形
 * 默认创建的验证码都是 字母+数字 的混合，也可以手动指定生成器 setGenerator(CodeGenerator generator) 来自定义生成方式。
 */
@RestController
@RequestMapping("/hutool")
public class HutoolCaptchaController {

    /**
     * 获取线条干扰的图形验证码
     */
    @GetMapping("/lineInterfereCode")
    public void createLineInterfereCode(HttpServletResponse response) throws IOException {
        // 创建线条干扰的图像验证码，指定验证码图片的 宽、高、验证码字符个数（默认5个）、干扰元素（这里是线条）的数量（默认150个）
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100, 5, 100);

        // 此时还没有生成验证码，需要调用方法生成：createCode()是生成全新的验证码和图形。
        // createCode 方法会生成一个全新的验证码和图形，原本的会被覆盖。
        // getCode 和 write 方法都是先检查是否已经存在验证码和图形，如果存在直接获取，不存在就调用 createCode 生成一个新的验证码和图形，下次可以直接获取。

        // lineCaptcha.createCode();

        // 获取验证码字符串
        String code = lineCaptcha.getCode();

        System.out.println(code);
        ServletOutputStream outputStream = response.getOutputStream();
        // 把图形验证码写到输出流或者文件中
        lineCaptcha.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }


    /**
     * 获取圆圈干扰的图形验证码
     */
    @GetMapping("/circleInterfereCode")
    public void createCircleInterfereCode(HttpServletResponse response) throws IOException {
        // 创建圆圈干扰的图形验证码，指定验证码图片的 宽、高、验证码字符个数（默认5个）、干扰元素（这里是圆圈）的数量（默认15个）
        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(200, 100, 5, 30);
        // 获取验证码字符串
        System.out.println(circleCaptcha.getCode());
        ServletOutputStream outputStream = response.getOutputStream();
        // 把图形验证码写到输出流或者文件中
        circleCaptcha.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }

    /**
     * 获取字符形变的图形验证码
     */
    @GetMapping("/shearCode")
    public void createShearCode(HttpServletResponse response) throws IOException {
        // 创建字符形变的图形验证码，指定验证码图片的 宽、高、验证码字符个数（默认5个）、干扰线的宽度（默认4个像素宽度）
        ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(250, 100, 4, 2);
        // 获取验证码字符串
        System.out.println(shearCaptcha.getCode());
        ServletOutputStream outputStream = response.getOutputStream();
        // 把图形验证码写到输出流或者文件中
        shearCaptcha.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }


    /**
     * 获取 gif格式 图形验证码
     */
    @GetMapping("/gifCode")
    public void createGifCode(HttpServletResponse response) throws IOException {
        // 创建gif格式 图形验证码，指定验证码图片的 宽、高、验证码字符个数（默认5个）
        GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(200, 100, 4);
        // 获取验证码字符串
        System.out.println(gifCaptcha.getCode());
        ServletOutputStream outputStream = response.getOutputStream();
        // 把图形验证码写到输出流或者文件中
        gifCaptcha.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }

    /**
     * 使用生成器自定义生成的验证码格式：
     * 获取 纯数字 图形验证码
     */
    @GetMapping("/numberCode")
    public void createNumberCode(HttpServletResponse response) throws IOException {
        // 创建随机生成器，每次从 字符串中取4位数字（生成的验证码的长度是4位），取出的数字可以重复
        RandomGenerator generator = new RandomGenerator("0123456789", 4);
        // 使用gif类型验证码，也可以使用其他类型的验证码，codeCount参数 是默认生成器生成的验证码长度，如果设置了新的生成器则以新生成器为准
        GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(200, 100, 0);
        // 设置生成器，会导致原本的 codeCount参数 无效，生成的验证码的长度以新的生成器为准
        gifCaptcha.setGenerator(generator);

        // 获取验证码字符串
        System.out.println(gifCaptcha.getCode());
        ServletOutputStream outputStream = response.getOutputStream();
        // 把图形验证码写到输出流或者文件中
        gifCaptcha.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }


    /**
     * 使用生成器自定义生成的验证码格式：
     * 获取 四则运算 图形验证码
     */
    @GetMapping("/mathCode")
    public void createMathCode(HttpServletResponse response) throws IOException {
        // 创建数学生成器，设置生成的 四则运算式表达式 中参与计算的最每一项最大可以有几位数，默认两位
        MathGenerator generator = new MathGenerator(2);
        // 使用线条干扰类型验证码，也可以使用其他类型的验证码，codeCount参数 是默认生成器生成的验证码长度，如果设置了新的生成器则以新生成器为准
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100, 0, 150);
        // 设置生成器，会导致原本的 codeCount参数 无效，生成的验证码的长度以新的生成器为准
        lineCaptcha.setGenerator(generator);

        // 获取验证码字符串，是一个四则运算表达式
        String code = lineCaptcha.getCode();
        // 计算表达式得到结果
        int res = (int) Calculator.conversion(code);
        System.out.printf("%s%d\n", code, res);

        ServletOutputStream outputStream = response.getOutputStream();
        // 把图形验证码写到输出流或者文件中
        lineCaptcha.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }


}
